package cn.iune.erp.accounting;

import java.math.BigDecimal;
import java.sql.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.justep.baas.Utils;

import cn.iune.common.response.MapMessage;
import cn.iune.erp.setting.IParamSettingService;
import cn.iune.erp.setting.ISettingService;
import cn.iune.system.service.ConvertUpMoney;

@Transactional
@Service
public class AccountingServiceImpl implements IAccountingService {
	
	@Autowired
	private IAccountVoucherService accountVoucherService;
	@Autowired
	private IAccountVoucherDetailService accountVoucherDetailService;
	
	@Autowired
	private IAccountCaptionService accountCaptionService;
	
	@Autowired
	private IPeriodCaptionService periodCaptionService;
	
	@Autowired
	private IAccountPeriodService accountPeriodService;
	
	@Autowired
	private IParamSettingService paramSettingService;
	
	@Autowired
	private ISettingService settingService;
	
	
	@Transactional
	@Override
	public Map<String,Object> accountVoucherConfirm(String rowID, String tUsercode, String tUsername, String userId, String employeeNo, String employeeName){
		AccountVoucher obj = accountVoucherService.getByID(rowID);
		
//		List<AccountVoucherDetail> objs = accountVoucherDetailService.getByMasterID(rowID);
		
		MapMessage mapMessage = new MapMessage(obj.getfID(),obj.getVoucherNo(),obj.getBillType(),obj.getBillTypeName()
				,MapMessage.STATUSINFO_SUCCESS_CODE//"http://www.iune.cn"
				,MapMessage.STATUSINFO_SUCCESS_MSG//"操作成功！"
				,MapMessage.STATUSINFO_SUCCESS_INFO//"操作成功！"
				,MapMessage.STATUSINFO_SUCCESS_FLAG//"success"
				);

		//首先审核从表
		int rtn = accountVoucherDetailService.confirmByMasterID(rowID);
		if (rtn != 0){
			mapMessage.setStatusCode("100001");
			mapMessage.setStatusMsg(MapMessage.STATUSINFO_FAILURE_MSG);
			mapMessage.setStatusInfo("从表提交失败！");
			mapMessage.setStatusFlag(MapMessage.STATUSINFO_FAILURE_FLAG);
			return mapMessage.toMap();
		}
		
		//然后审核主表
		rtn = accountVoucherService.confirm(rowID);
		if (rtn != 0){
			mapMessage.setStatusCode("100001");
			mapMessage.setStatusMsg(MapMessage.STATUSINFO_FAILURE_MSG);
			mapMessage.setStatusInfo("主表提交失败！");
			mapMessage.setStatusFlag(MapMessage.STATUSINFO_FAILURE_FLAG);
			return mapMessage.toMap();
		}
		
		//自动审核
		if(accountVoucherService.getByID(rowID).getFlowType()==0){
			//审核
			Map<String,Object> map = this.accountVoucherAgreeIt(rowID, tUsercode, tUsername, userId, employeeNo, employeeName);
			mapMessage.fromMap(map);
			//检查结果是否包括失败状态，如果包括，直接返回
			if (mapMessage.getStatusFlag().equals(MapMessage.STATUSINFO_FAILURE_FLAG)){
				return mapMessage.toMap();
			}
			
		}
		
		
		return mapMessage.toMap();
	}

	@Transactional
	@Override
	public Map<String,Object> accountVoucherActive(String rowID){
		AccountVoucher obj = accountVoucherService.getByID(rowID);
		
//		List<AccountVoucherDetail> objs = accountVoucherDetailService.getByMasterID(rowID);
		
		MapMessage mapMessage = new MapMessage(obj.getfID(),obj.getVoucherNo(),obj.getBillType(),obj.getBillTypeName()
				,MapMessage.STATUSINFO_SUCCESS_CODE//"http://www.iune.cn"
				,MapMessage.STATUSINFO_SUCCESS_MSG//"操作成功！"
				,MapMessage.STATUSINFO_SUCCESS_INFO//"操作成功！"
				,MapMessage.STATUSINFO_SUCCESS_FLAG//"success"
				);

		//首先审核从表
		int rtn = accountVoucherDetailService.activeByMasterID(rowID);
		if (rtn != 0){
			mapMessage.setStatusCode("100001");
			mapMessage.setStatusMsg(MapMessage.STATUSINFO_FAILURE_MSG);
			mapMessage.setStatusInfo("从表撤销提交失败！");
			mapMessage.setStatusFlag(MapMessage.STATUSINFO_FAILURE_FLAG);
			return mapMessage.toMap();
		}
		
		//然后审核主表
		rtn = accountVoucherService.active(rowID);
		if (rtn != 0){
			mapMessage.setStatusCode("100001");
			mapMessage.setStatusMsg(MapMessage.STATUSINFO_FAILURE_MSG);
			mapMessage.setStatusInfo("主表撤销提交失败！");
			mapMessage.setStatusFlag(MapMessage.STATUSINFO_FAILURE_FLAG);
			return mapMessage.toMap();
		}
		
		return mapMessage.toMap();
	}

	//审核出入库单（改造为主从表不关联审核）
	@Transactional
	@Override
	public Map<String,Object> accountVoucherAgreeIt(String rowID, String tUsercode, String tUsername, String userId, String employeeNo, String employeeName){
		AccountVoucher obj = accountVoucherService.getByID(rowID);
		
//		List<AccountVoucherDetail> objs = accountVoucherDetailService.getByMasterID(rowID);
		
		MapMessage mapMessage = new MapMessage(obj.getfID(),obj.getVoucherNo(),obj.getBillType(),obj.getBillTypeName()
				,MapMessage.STATUSINFO_SUCCESS_CODE//"http://www.iune.cn"
				,MapMessage.STATUSINFO_SUCCESS_MSG//"操作成功！"
				,MapMessage.STATUSINFO_SUCCESS_INFO//"操作成功！"
				,MapMessage.STATUSINFO_SUCCESS_FLAG//"success"
				);
		
		
//		accountVoucherDetailService.agreeItByMasterID(rowID);
		List<AccountVoucherDetail> as = accountVoucherDetailService.getByMasterID(rowID);
		for(AccountVoucherDetail a : as){
			accountVoucherDetailService.agreeIt(a);
			this.doIt(a);
		}

		//然后审核主表
		accountVoucherService.agreeIt(rowID, tUsercode, tUsername, userId);
		
		return mapMessage.toMap();

	}

	@Transactional
	@Override
	public Map<String,Object> accountVoucherUnAgree(String rowID){
		AccountVoucher obj = accountVoucherService.getByID(rowID);
		
//		List<AccountVoucherDetail> objs = accountVoucherDetailService.getByMasterID(rowID);
		
		MapMessage mapMessage = new MapMessage(obj.getfID(),obj.getVoucherNo(),obj.getBillType(),obj.getBillTypeName()
				,MapMessage.STATUSINFO_SUCCESS_CODE//"http://www.iune.cn"
				,MapMessage.STATUSINFO_SUCCESS_MSG//"操作成功！"
				,MapMessage.STATUSINFO_SUCCESS_INFO//"操作成功！"
				,MapMessage.STATUSINFO_SUCCESS_FLAG//"success"
				);
		
//		accountVoucherDetailService.unAgreeByMasterID(rowID);
		List<AccountVoucherDetail> as = accountVoucherDetailService.getByMasterID(rowID);
		for(AccountVoucherDetail a : as){
			accountVoucherDetailService.unAgree(a);
			this.unDo(a);
		}

		//然后审核主表
		accountVoucherService.unAgree(rowID);
		
		return mapMessage.toMap();

	}

	@Transactional
	@Override
	public int accountVoucherClose(String rowID){

		//首先审核从表
		int rtn = accountVoucherDetailService.closeByMasterID(rowID);
		if (rtn != 0){
			return -1;
		}
		
		//然后审核主表
		rtn = accountVoucherService.close(rowID);
		if (rtn != 0){
			return -1;
		}
		
		return 0;
	}

	@Transactional
	@Override
	public int accountVoucherOpen(String rowID){

		//首先审核从表
		int rtn = accountVoucherDetailService.openByMasterID(rowID);
		if (rtn != 0){
			return -1;
		}
		
		//然后审核主表
		rtn = accountVoucherService.open(rowID);
		if (rtn != 0){
			return -1;
		}
		
		return 0;
	}
	
	
	
	@Transactional
	private int doIt(AccountVoucherDetail obj){
		return 0;
	}
	
	@Transactional
	private int unDo(AccountVoucherDetail obj){
		return 0;
	}
	
	@Transactional
	@Override
    public void afterInsert(AccountVoucherDetail obj){
		System.out.println("AccountingServiceImpl.afterInsert");
	}
	
	@Transactional
	@Override
    public void beforeDelete(String fID){
		System.out.println("AccountingServiceImpl.beforeDelete");
	}
	
	
	
	
	
	
	
	
	
	//会计科目写入月档AccountCaption  insert PeriodCaption
	@Transactional
    private PeriodCaption captionIntoPeriod(String yearNo, String periodNo, AccountCaption accountCaption, String userId, String enterpriseNo){
		
		if(accountCaption== null) return null;
		
		String captionNo = accountCaption.getCaptionNo();
		String captionID = accountCaption.getfID();
		String captionName = accountCaption.getCaptionName();
		String captionFullName = accountCaption.getCaptionFullName();
		
		String billType = accountCaption.getBillType();
		String billTypeName = accountCaption.getBillTypeName();
		
		int dob = accountCaption.getDob();//余额方向
		
		String currency = accountCaption.getCurrency();
		String currencyLabel = accountCaption.getCurrencyLabel();
		
		int nodeLevel = accountCaption.getNodeLevel();
		String nodeKind = accountCaption.getNodeKind();
		String sortNo = accountCaption.getSortNo();
		String fParent = accountCaption.getfParent();

		String enterpriseName = accountCaption.getEnterpriseName();
		
		PeriodCaption periodCaption = periodCaptionService.insert(yearNo, periodNo, captionID, captionNo, captionName, captionFullName, billType, billTypeName, dob, currency, currencyLabel, nodeLevel, nodeKind, sortNo, fParent, userId, enterpriseNo, enterpriseName);
		return periodCaption;
	}

		
	//会计期初开账
	@Transactional
	@Override
	public JSONObject accountingInitial(String yearNo, String periodNo, String userId, String enterpriseNo){
		
		JSONObject json = new JSONObject();
		
		//获取会计期间
		AccountPeriod accountPeriod  = accountPeriodService.getByNo(yearNo, periodNo, enterpriseNo);
		if(accountPeriod==null) {
			json.put("code", -1);
			json.put("msg", "failure");
			json.put("info", "会计期间档案不存在！");
			return json;
		}

		//获取全部会计档案
		List<AccountCaption> list = accountCaptionService.getList(enterpriseNo);
		for(AccountCaption accountCaption: list) {
			//循环写入月档
			this.captionIntoPeriod(yearNo, periodNo, accountCaption, userId, enterpriseNo);
		}

		String yearPeriodNo = yearNo.concat("-").concat(periodNo);
		
		//五、更新现行年月
		//(2)、更新

		//更新会计开账年月，同时会更新现行会计期间
		paramSettingService.updateKJKZNY(yearPeriodNo, enterpriseNo);
		
		json.put("code", 0);
		json.put("msg", "success");
		return json;
	}
	
	//结束开账
	@Transactional
	@Override
	public JSONObject accountingInitSubmit(String yearNo, String periodNo, String enterpriseNo){
		
		JSONObject json = new JSONObject();
	
		periodCaptionService.initSubmit(yearNo, periodNo, enterpriseNo);
	
		//更新会计开账结束标志
		paramSettingService.updateKJKZOK(1, enterpriseNo);
		
		json.put("code", 0);
		json.put("msg", "success");
		return json;
	}
	
	//取消结束开账
	@Transactional
	@Override
	public JSONObject accountingInitActive(String yearNo, String periodNo, String enterpriseNo){
		
		JSONObject json = new JSONObject();
	
		periodCaptionService.initActive(yearNo, periodNo, enterpriseNo);
	
		//更新会计开账结束标志
		paramSettingService.updateKJKZOK(0, enterpriseNo);
		
		json.put("code", 0);
		json.put("msg", "success");
		return json;
	}
	
	//清除会计期初开账数据。之后重新开账
	@Transactional
	@Override
	public JSONObject accountingDelete(String yearNo, String periodNo, String enterpriseNo){
		
		JSONObject json = new JSONObject();
		
		//获取会计期间
		AccountPeriod accountPeriod  = accountPeriodService.getByNo(yearNo, periodNo, enterpriseNo);
		if(accountPeriod==null) {
			json.put("code", -1);
			json.put("msg", "failure");
			json.put("info", "会计期间档案不存在！");
			return json;
		}
	
		periodCaptionService.deleteByPeriod(yearNo, periodNo, enterpriseNo);
		
		json.put("code", 0);
		json.put("msg", "success");
		return json;
	}
	
	
	
	//由分录底稿生成会计凭证（反）
	@Transactional
	@Override
	public int formalKJPZ(AccountVoucher accountVoucher, String cUsercode, String cUsername, String userId){
		String voucherNo = null;
		if(accountVoucher.getFormalFlag()==0) {
			//待抛转为正式凭证
			//获取凭证号
			String billType = accountVoucher.getBillType();
			String enterpriseNo = accountVoucher.getEnterpriseNo();
			
			voucherNo = settingService.getMaxCode(billType, enterpriseNo);
			accountVoucher.setFormalFlag(1);
		}else {
			//已经抛转
			accountVoucher.setFormalFlag(0);
		}
		
		accountVoucher.setVoucherNo(voucherNo);
		accountVoucherService.update(accountVoucher);
		
		List<AccountVoucherDetail> list = accountVoucherDetailService.getByMasterID(accountVoucher.getfID());
		for(AccountVoucherDetail detail: list) {
			detail.setVoucherNo(voucherNo);
			accountVoucherDetailService.update(detail);
		}
		
		return 0;
	}
	
	//由分录底稿生成会计凭证（反）
	@Transactional
	@Override
	public JSONObject formalKJPZ(String fID, String cUsercode, String cUsername, String userId){
		
		JSONObject json = new JSONObject();
		AccountVoucher accountVoucher = accountVoucherService.getByID(fID);
		if(accountVoucher==null) {
			json.put("code", -1);
			json.put("msg", "failure");
			json.put("info", "单据档案不存在！");
			return json;
		}
	
		int rtn = this.formalKJPZ(accountVoucher, cUsercode, cUsername, userId);
		if(rtn!=0) {
			json.put("code", -2);
			json.put("msg", "failure");
			json.put("info", "抛转凭证时返回错误值！");
			return json;
		}
		
		json.put("code", 0);
		json.put("msg", "success");
		return json;
	}

	
	

	//记账，被循环调用，是为了支持更新上一级总账
	@Transactional
    private PeriodCaption bookkeeping(String yearNo, String periodNo, String captionNo, BigDecimal debitAmount, BigDecimal creditAmount, int postedFlag, String rUsercode, String rUsername, String userId, String enterpriseNo){
		
		//获取总账记录
		PeriodCaption periodCaption = periodCaptionService.getByNo(yearNo, periodNo, captionNo, enterpriseNo);
		if(periodCaption==null) {
			AccountCaption accountCaption = accountCaptionService.getByNo(captionNo, enterpriseNo);
			/*
			String captionID = accountCaption.getfID();
			String captionName = accountCaption.getCaptionName();
			String captionFullName = accountCaption.getCaptionFullName();
			
			String billType = accountCaption.getBillType();
			String billTypeName = accountCaption.getBillTypeName();
			
			int dob = accountCaption.getDob();//余额方向
			String dobLabel = accountCaption.getDobLabel();//余额方向
			
			String currency = accountCaption.getCurrency();
			String currencyLabel = accountCaption.getCurrencyLabel();
			
			int nodeLevel = accountCaption.getNodeLevel();
			String nodeKind = accountCaption.getNodeKind();
			String sortNo = accountCaption.getSortNo();
			String fParent = accountCaption.getfParent();

			String enterpriseName = accountCaption.getEnterpriseName();
			
			periodCaption = periodCaptionService.insert(yearNo, periodNo, captionID, captionNo, captionName, captionFullName, billType, billTypeName, dob, dobLabel, currency, currencyLabel, nodeLevel, nodeKind, sortNo, fParent, userId, enterpriseNo, enterpriseName);
			*/
			periodCaption = this.captionIntoPeriod(yearNo, periodNo, accountCaption, userId, enterpriseNo);
		}
		
		//开始记账

		if(postedFlag==0) {
			//还未过账，过账
			System.out.println("还未过账，过账postedFlag-->>"+postedFlag);
			//本期
			periodCaption.setDebitPeriod(periodCaption.getDebitPeriod().add(debitAmount));
			periodCaption.setCreditPeriod(periodCaption.getCreditPeriod().add(creditAmount));
			//本年
			periodCaption.setDebitYear(periodCaption.getDebitYear().add(debitAmount));
			periodCaption.setCreditYear(periodCaption.getCreditYear().add(creditAmount));
			//笔数
			if(debitAmount.compareTo(BigDecimal.ZERO)!=0) {
				periodCaption.setDebitCount(periodCaption.getDebitCount() + 1);
				periodCaption.setDebitCountYear(periodCaption.getDebitCountYear() + 1);
			}
			if(creditAmount.compareTo(BigDecimal.ZERO)!=0) {
				periodCaption.setCreditCount(periodCaption.getCreditCount() + 1);
				periodCaption.setCreditCountYear(periodCaption.getCreditCountYear() + 1);
			}
			//期末
			periodCaption.setDebitEnd(periodCaption.getDebitEnd().add(debitAmount));
			periodCaption.setCreditEnd(periodCaption.getCreditEnd().add(creditAmount));
			//年末
			periodCaption.setDebitYearEnd(periodCaption.getDebitYearEnd().add(debitAmount));
			periodCaption.setCreditYearEnd(periodCaption.getCreditYearEnd().add(creditAmount));
		}
		
		if(postedFlag==1) {
			//已经过账，撤回
			System.out.println("已经过账，撤回postedFlag-->>"+postedFlag);
			//本期
			periodCaption.setDebitPeriod(periodCaption.getDebitPeriod().subtract(debitAmount));
			periodCaption.setCreditPeriod(periodCaption.getCreditPeriod().subtract(creditAmount));
			//本年
			periodCaption.setDebitYear(periodCaption.getDebitYear().subtract(debitAmount));
			periodCaption.setCreditYear(periodCaption.getCreditYear().subtract(creditAmount));
			//本期笔数
			if(debitAmount.compareTo(BigDecimal.ZERO)!=0) {
				periodCaption.setDebitCount(periodCaption.getDebitCount() - 1);
				periodCaption.setDebitCountYear(periodCaption.getDebitCountYear() - 1);
			}
			if(creditAmount.compareTo(BigDecimal.ZERO)!=0) {
				periodCaption.setCreditCount(periodCaption.getCreditCount() - 1);
				periodCaption.setCreditCountYear(periodCaption.getCreditCountYear() - 1);
			}
			//期末
			periodCaption.setDebitEnd(periodCaption.getDebitEnd().subtract(debitAmount));
			periodCaption.setCreditEnd(periodCaption.getCreditEnd().subtract(creditAmount));
			//年末
			periodCaption.setDebitYearEnd(periodCaption.getDebitYearEnd().subtract(debitAmount));
			periodCaption.setCreditYearEnd(periodCaption.getCreditYearEnd().subtract(creditAmount));
		}

		//余额计算
		BigDecimal balanceEnd = BigDecimal.ZERO;
		BigDecimal balanceYearEnd = BigDecimal.ZERO;
		if(periodCaption.getDob()==1) {
			//借方余额
			balanceEnd = periodCaption.getDebitEnd().subtract(periodCaption.getCreditEnd());
			balanceYearEnd = periodCaption.getDebitYearEnd().subtract(periodCaption.getCreditYearEnd());
		}
		if(periodCaption.getDob()==-1) {
			//贷方余额
			balanceEnd = periodCaption.getCreditEnd().subtract(periodCaption.getDebitEnd());
			balanceYearEnd = periodCaption.getCreditYearEnd().subtract(periodCaption.getDebitYearEnd());
		}
		periodCaption.setBalanceEnd(balanceEnd);
		periodCaption.setBalanceYearEnd(balanceYearEnd);
		
		//更新
		periodCaptionService.update(periodCaption);
		
		return periodCaption;
	}
	
	//按单据号过帐/记账
	@Transactional
    private int bookkeeping(String yearNo, String periodNo, AccountVoucher accountVoucher, String rUsercode, String rUsername, String userId, String enterpriseNo){
		//过账标识
		int postedFlag = accountVoucher.getPostedFlag();
		
		//获取凭证从表
		List<AccountVoucherDetail> as = accountVoucherDetailService.getByMasterID(accountVoucher.getfID());
		for(AccountVoucherDetail a : as){
			
			String captionNo= a.getCaptionNo();
			
			BigDecimal direction = new BigDecimal(a.getDirection());
			BigDecimal debitAmount = a.getDebitAmount().multiply(direction).setScale(2, BigDecimal.ROUND_HALF_UP);
			BigDecimal creditAmount = a.getCreditAmount().multiply(direction).setScale(2, BigDecimal.ROUND_HALF_UP);
			
			//记账
			/*
			PeriodCaption periodCaption = null;
			do {
				periodCaption = this.bookkeeping(yearNo, periodNo, captionNo, debitAmount, creditAmount, postedFlag, userId, rUsercode, rUsername, enterpriseNo);
				String fParent = periodCaption.getfParent();
				if(fParent!=null) {
					AccountCaption accountCaption = accountCaptionService.getByID(fParent);
					//赋值上一级总账
					captionNo = accountCaption.getCaptionNo();
				}
			}while(periodCaption.getNodeLevel()>1);
			*/
			//记账
			PeriodCaption periodCaption = this.bookkeeping(yearNo, periodNo, captionNo, debitAmount, creditAmount, postedFlag, rUsercode, rUsername, userId, enterpriseNo);
			
			//记账凭证明细表中的结存余额
			a.setBalanceAmount(periodCaption.getBalanceEnd());
			accountVoucherDetailService.update(a);
			
			//登记总账的上一级
			while(periodCaption.getNodeLevel()>1) {
				String fParent = periodCaption.getfParent();
				if(fParent!=null) {
					AccountCaption accountCaption = accountCaptionService.getByID(fParent);
					//赋值上一级总账
					captionNo = accountCaption.getCaptionNo();
					periodCaption = this.bookkeeping(yearNo, periodNo, captionNo, debitAmount, creditAmount, postedFlag, rUsercode, rUsername, userId, enterpriseNo);
				}
			}
		}
		
		if(postedFlag==0) {
			//还未过账，过账
			System.out.println("主表：还未过账，过账postedFlag-->>"+postedFlag);
			//更新凭证过账标志
			accountVoucher.setPostedFlag(1);
			accountVoucher.setPostedDate(Utils.getCurrentDate());
			accountVoucher.setrUsercode(rUsercode);
			accountVoucher.setrUsername(rUsername);
			accountVoucher.setrDatetime(Utils.getCurrentDateTime());
		}
		if(postedFlag==1) {
			//已经过账，撤回
			System.out.println("主表：已经过账，撤回postedFlag-->>"+postedFlag);
			//更新凭证过账标志
			accountVoucher.setPostedFlag(0);
			accountVoucher.setPostedDate(null);
			accountVoucher.setrUsercode(null);
			accountVoucher.setrUsername(null);
			accountVoucher.setrDatetime(null);
		}

		accountVoucherService.update(accountVoucher);
		
//		json.put("code", 0);
//		json.put("msg", "success");
//		json.put("code", "过账成功！");
		return 0;
	}
	
	//按单据号数组过帐/记账
	@Transactional
	@Override
    public JSONObject bookkeeping(String yearNo, String periodNo, String[] voucherNos, String rUsercode, String rUsername, String userId, String enterpriseNo){
		JSONObject json = new JSONObject();
		
		for(int i=0;i<voucherNos.length;i++) {
			AccountVoucher accountVoucher = accountVoucherService.getByNo(voucherNos[i], enterpriseNo);
			if(accountVoucher==null) {
				json.put("code", -1);
				json.put("msg", "failure");
				json.put("info", "会计凭证不存在！");
				return json;
			}
			
			int rtn = this.bookkeeping(yearNo, periodNo, accountVoucher, rUsercode, rUsername, userId, enterpriseNo);
			switch(rtn) {
				case -3:
					json.put("code", -3);
					json.put("msg", "failure");
					json.put("info", "会计科目不能为空！");
					break;
				case -4:
					json.put("code", -4);
					json.put("msg", "failure");
					json.put("info", "会计科目档案不存在！");
					break;
			}
			
			if(rtn<0) {
				return json;
			}
		}

		json.put("code", 0);
		json.put("msg", "success");
		json.put("info", "过账完成！");
		return json;
	}
	
	
	//按单据号过帐/记账（或者撤回）
	@Transactional
	@Override
    public JSONObject bookkeeping(String voucherNo, String rUsercode, String rUsername, String userId, String enterpriseNo){
		JSONObject json = new JSONObject();
		AccountVoucher accountVoucher = accountVoucherService.getByNo(voucherNo, enterpriseNo);
		if(accountVoucher==null) {
			json.put("code", -1);
			json.put("msg", "failure");
			json.put("info", "会计凭证不存在！");
			return json;
		}
		
		Date orderDate = accountVoucher.getOrderDate();
		AccountPeriod accountPeriod = accountPeriodService.getByDate(orderDate, enterpriseNo);
		if(accountPeriod==null) {
			json.put("code", -2);
			json.put("msg", "failure");
			json.put("info", "会计期间档案不存在！");
			return json;
		}

		String yearNo = accountPeriod.getYearNo();
		String periodNo = accountPeriod.getPeriodNo();
		
		//还未过账，过账
		int rtn = this.bookkeeping(yearNo, periodNo, accountVoucher, rUsercode, rUsername, userId, enterpriseNo);
		switch(rtn) {
			case -3:
				json.put("code", -3);
				json.put("msg", "failure");
				json.put("info", "会计科目不能为空！");
				break;
			case -4:
				json.put("code", -4);
				json.put("msg", "failure");
				json.put("info", "会计科目档案不存在！");
				break;
		}
		
		if(rtn<0) {
			return json;
		}
		

		json.put("code", 0);
		json.put("msg", "success");
		json.put("info", "过账完成！");
		return json;
	}
	

	//会计月结（这种方案可以保证会计科目档案中新增的会计科目进入月档）
	/*
	@Transactional
	private int accountingNext(String yearNo, String periodNo, String yearNoNext, String periodNoNext, String userId, String enterpriseNo){

		//获取全部会计档案
		List<AccountCaption> list = accountCaptionService.getList(enterpriseNo);
		for(AccountCaption accountCaption: list) {
			String captionNo = accountCaption.getCaptionNo();

			//获取当期数据
			PeriodCaption obj = periodCaptionService.getByNo(yearNo, periodNo, captionNo, enterpriseNo);

			//循环写入下期月档
			PeriodCaption periodCaption = this.captionIntoPeriod(yearNoNext, periodNoNext, accountCaption, userId, enterpriseNo);

			if("12".equals(periodNo)) {
				//如果当前是12月份，就是年底

				///////////年度////////////////
				//年初
				BigDecimal debitYearBegin = obj.getDebitYearEnd();
				BigDecimal creditYearBegin = obj.getCreditYearEnd();
				BigDecimal balanceYearBegin = obj.getBalanceYearEnd();
				
				//---------------------------------------------------
				
				//续写本年期初
				periodCaption.setDebitYearBegin(debitYearBegin);
				periodCaption.setCreditYearBegin(creditYearBegin);
				periodCaption.setBalanceYearBegin(balanceYearBegin);
				//续写本年期末
				periodCaption.setDebitYearEnd(debitYearBegin);
				periodCaption.setCreditYearEnd(debitYearBegin);
				periodCaption.setBalanceYearEnd(debitYearBegin);
				////////////////////////////////
					
			}else {

				///////////年度////////////////
				//年初
				BigDecimal debitYearBegin = obj.getDebitYearBegin();
				BigDecimal creditYearBegin = obj.getCreditYearBegin();
				BigDecimal balanceYearBegin = obj.getBalanceYearBegin();
				//本年累计
				BigDecimal debitYear = obj.getDebitYear();
				BigDecimal creditYear = obj.getCreditYear();
				int debitCountYear = obj.getDebitCountYear();
				int creditCountYear = obj.getCreditCountYear();
				//年末
				BigDecimal debitYearEnd = obj.getDebitYearEnd();
				BigDecimal creditYearEnd = obj.getCreditYearEnd();
				BigDecimal balanceYearEnd = obj.getBalanceYearEnd();
				
				//---------------------------------------------------
				
				//续写本年期初
				periodCaption.setDebitYearBegin(debitYearBegin);
				periodCaption.setCreditYearBegin(creditYearBegin);
				periodCaption.setBalanceYearBegin(balanceYearBegin);
				//续写本年累计
				periodCaption.setDebitYear(debitYear);
				periodCaption.setCreditYear(creditYear);
				periodCaption.setDebitCountYear(debitCountYear);
				periodCaption.setCreditCountYear(creditCountYear);
				//续写本年期末
				periodCaption.setDebitYearEnd(debitYearEnd);
				periodCaption.setCreditYearEnd(creditYearEnd);
				periodCaption.setBalanceYearEnd(balanceYearEnd);
				////////////////////////////////
				
			}

			///////////月档/////////////////////////////
			//期初
			BigDecimal debitBegin = obj.getDebitEnd();
			BigDecimal creditBegin = obj.getCreditEnd();
			BigDecimal balanceBegin = obj.getBalanceEnd();
			
			//-------------------------------------------------
			
			//结转期初
			periodCaption.setDebitBegin(debitBegin);
			periodCaption.setCreditBegin(creditBegin);
			periodCaption.setBalanceBegin(balanceBegin);
			//同时写入期末
			periodCaption.setDebitEnd(debitBegin);
			periodCaption.setCreditEnd(creditBegin);
			periodCaption.setBalanceEnd(balanceBegin);
			///////////////////////////////////////////////
			
			periodCaptionService.update(periodCaption);
		}
		
		return 0;
	}
	*/

	//会计月结
	@Transactional
	@Override
	public JSONObject accountingNext(String yearNo, String periodNo, String userId, String enterpriseNo){
		
		JSONObject json = new JSONObject();
		
		//获取会计期间
//		AccountPeriod accountPeriod  = accountPeriodService.getByNo(yearNo, periodNo, enterpriseNo);
//		if(accountPeriod==null) {
//			json.put("code", -1);
//			json.put("msg", "failure");
//			json.put("code", "会计期间档案不存在！");
//			return json;
//		}

		//获取下一个会计期间
		String value = accountPeriodService.getYearPeriodNext(yearNo, periodNo, enterpriseNo);
		if(value==null) {
			//系统中未录入前一个会计期间，表示已经是最前一个期间啦，不能执行。
			json.put("code", -1);
			json.put("msg", "failure");
			json.put("info", "会计期间数据不存在，请录入会计期间数据！");
			return json;
		}

		//将库存现行年月调整至原库存现行年月之后
		//(1)、首先获取下一个期间
		//（2)、结转本期期末数据（作为下期期初数据）
		String yearNoNext = value.split("-")[0];
		String periodNoNext = value.split("-")[1];
		
		//7、结转本期期末数据（作为下期期初数据）；
//		this.accountingNext(yearNo, periodNo, yearNoNext, periodNoNext, userId, enterpriseNo);
		periodCaptionService.next(yearNo, periodNo, yearNoNext, periodNoNext, userId, enterpriseNo);

		//五、更新现行年月
		//将库存现行年月调整至原库存现行年月之后
		//(2)、更新

		//更新现行会计期间
		paramSettingService.updateKJXXNY(value, enterpriseNo);
		
		json.put("code", 0);
		json.put("msg", "success");
		return json;
	}

	
	
	//////////////////////////////////////////////////////////////////
	

	//自动分录
	@Override
    public JSONObject automaticEntry(		
    		String origin,
    		String originName,
    		String originNo,
    		String billType,
    		String billTypeName,
    		int direction,
    		int attachQuantity, //附件数量
    		String currency,//币种
    		String currencyLabel,//币种
    		String comments,
   		
    		JSONArray entries,

			String cUsercode,
			String cUsername,
			String userId,
			String employeeNo,
			String employeeName,
			String enterpriseNo,
			String enterpriseName
    	){

		JSONObject json = new JSONObject();
		
		String systemCode = null;
		int flowType = 1;
		
		int formalFlag = 0;

		AccountVoucher accountVoucher = this.insert(origin, originName, originNo, systemCode, billType, billTypeName, direction, attachQuantity, flowType, comments, entries, formalFlag, cUsercode, cUsername, userId, employeeNo, employeeName, enterpriseNo, enterpriseName);
		if(accountVoucher==null) {
			json.put("code", -2);
			json.put("msg","failure");
			json.put("info","生成会计分录失败！");
			return json;
		}
		
		if(formalFlag==1) {
			//抛转成会计凭证啦，可以提交和审批
			this.accountVoucherConfirm(accountVoucher.getfID(), cUsercode, cUsername, userId, employeeNo, employeeName);
			this.accountVoucherAgreeIt(accountVoucher.getfID(), cUsercode, cUsername, userId, employeeNo, employeeName);
		}
		
		json.put("code", 0);
		json.put("msg","success");
		json.put("vouherNo",accountVoucher.getVoucherNo());
		return json;
	}
		

	//生成分录底稿（可以直接生成会计凭证）
	@Override
    public AccountVoucher insert(		
    		String origin,
    		String originName,
    		String originNo,
    		String systemCode, 
    		String billType,
    		String billTypeName, 
    		int direction,
    		int attachQuantity, //附件数量
    		int flowType, 
    		String comments,
    		JSONArray entries,
    		
    		int formalFlag, //是否直接生成凭证
    		
			String cUsercode,
			String cUsername,
			String userId,
			String employeeNo,
			String employeeName,
			String enterpriseNo,
			String enterpriseName
    	){
		
		//单号
		/*
		Map<String,Object> map = systemCodeService.getBillParam(billType, enterpriseNo);
		String billTypeName = (String) map.get("billTypeName");
		String systemCode = (String) map.get("systemCode");
		int flowType = (int) map.get("flowType");
//		String revOpay = (String) map.get("revOpay");
//		int direction = (int) map.get("direction");
//		String costingCode = (String) map.get("costingCode");
		String autoCode = (String) map.get("autoCode");
//		String origin = (String) map.get("origin");
//		String originName = (String) map.get("originName");
		String billNo = (String) map.get("billNo");
		*/
		
//		AccountVoucher accountVoucher = accountVoucherService.packing(billType, billTypeName, systemCode, flowType, direction, autoCode, origin, originName, billNo, cUsercode, cUsername, userId, enterpriseNo, enterpriseName);
		AccountVoucher accountVoucher = accountVoucherService.packing(origin, originName, originNo, billType, billTypeName, systemCode, flowType, direction, cUsercode, cUsername, userId, enterpriseNo, enterpriseName);
		
		accountVoucher.setEmployeeNo(employeeNo);
		accountVoucher.setEmployeeName(employeeName);
		
//		accountVoucher.setOrigin(origin);
//		accountVoucher.setOriginName(originName);
//		accountVoucher.setOriginNo(originNo);
		
		accountVoucher.setDirection(direction);
		accountVoucher.setAttachQuantity(attachQuantity);
		
		accountVoucher.setComments(comments);
		
		BigDecimal debitAmountSum = BigDecimal.ZERO;       //借方金额
		BigDecimal creditAmountSum = BigDecimal.ZERO;       //贷方金额
		
		for(int i=0;i<entries.size();i++) {
			JSONObject entry = entries.getJSONObject(i);
			
			/////////////////////////////////////////////////////////
			
			int dob = entry.getIntValue("dob");
			
			String captionID = entry.getString("captionID");
			String captionNo = entry.getString("captionNo");//科目编码
			String captionName = entry.getString("captionName");
			String captionFullName = entry.getString("captionFullName");//科目名称
			
			BigDecimal entryAmount = entry.getBigDecimal("entryAmount");   //分录金额
			String summarys = entry.getString("summarys");//摘要

			String dealObject = entry.getString("dealObject");
			String dealObjectLabel = entry.getString("dealObjectLabel");
			String dealObjectID = entry.getString("dealObjectID");
			String dealObjectNo = entry.getString("dealObjectNo");
			String shortName = entry.getString("shortName");
			String dealObjectName = entry.getString("dealObjectName");
			
			BigDecimal debitAmount = BigDecimal.ZERO;   //借方金额
			BigDecimal creditAmount = BigDecimal.ZERO;  //贷方金额
			if(dob==1) {
				//借方
				debitAmount = entryAmount;
			}
			if(dob==-1) {
				//贷方
				creditAmount = entryAmount;
			}
			/////////////////////////////////////////////////////////

			AccountVoucherDetail accountVoucherDetail = accountVoucherDetailService.packing(accountVoucher);
			
			accountVoucherDetail.setDob(dob);
			
			accountVoucherDetail.setCaptionID(captionID);
			accountVoucherDetail.setCaptionNo(captionNo);
			accountVoucherDetail.setCaptionName(captionName);
			accountVoucherDetail.setCaptionFullName(captionFullName);
			
			accountVoucherDetail.setEntryAmount(entryAmount);
			accountVoucherDetail.setSummarys(summarys);
			
			accountVoucherDetail.setDealObject(dealObject);
			accountVoucherDetail.setDealObjectLabel(dealObjectLabel);
			//客户
			if("cus".equals(dealObject)) {
				accountVoucherDetail.setCustomerID(dealObjectID);
				accountVoucherDetail.setCustomerNo(dealObjectNo);
				accountVoucherDetail.setCshortName(shortName);
				accountVoucherDetail.setCustomerName(dealObjectName);
			}
			//供应商
			if("pro".equals(dealObject)) {
				accountVoucherDetail.setProviderID(dealObjectID);
				accountVoucherDetail.setProviderNo(dealObjectNo);
				accountVoucherDetail.setPshortName(shortName);
				accountVoucherDetail.setProviderName(dealObjectName);
			}
			
			accountVoucherDetail.setDebitAmount(debitAmount);
			accountVoucherDetail.setCreditAmount(creditAmount);
			
			accountVoucherDetailService.insert(accountVoucherDetail);
			
			//汇总
			debitAmountSum = debitAmountSum.add(accountVoucherDetail.getDebitAmount());
			creditAmountSum = creditAmountSum.add(accountVoucherDetail.getCreditAmount());
			
			//行数增加
			accountVoucher.setMaxDetailNo(accountVoucher.getMaxDetailNo() + 1);
		}
		
		//写入主表汇总金额
		accountVoucher.setDebitAmount(debitAmountSum);
		accountVoucher.setCreditAmount(creditAmountSum);
		//大写金额，参数被带进来之前已经试算平衡过啦。
		String wordsAmount = ConvertUpMoney.toChinese(debitAmountSum.toString());
		accountVoucher.setWordsAmount(wordsAmount);
		
		accountVoucherService.insert(accountVoucher);
		
		//判断是否直接生成凭证
		if(formalFlag==1) {
			this.formalKJPZ(accountVoucher, cUsercode, cUsername, userId);
		}
		
		return accountVoucher;
	}

	
	
	////////////////////////////////////////////////////////////////
	
	
	

}
